﻿package com.model
{
	import com.main.Observer;
	import com.tools.XmlLoader;
	import com.tools.XmlParser;
	import com.tools.notifications.XmlEvent;
	import com.tools.notifications.AvailableDataEvent;
	import com.conf.PlayerSpec;
	
	/////////////////////////////////////////////////////////////////////////////////////////////////////////
	// PlayerModel ::
	// - implémente le design pattern MVC
	/////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	public class PlayerModel extends Observer
	{
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		// MEMBRES DE CLASSE
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		private var xmlLoader			: XmlLoader ;
		public var xmlParser			: XmlParser = new XmlParser ( );
		private static const ECHEC_UINT	: uint = 111;
		
		public var skinsList			: Array;
		public var currentSkin			: String = new String();
		private var type				: String;
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		// CONSTRUCTEUR
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		function PlayerModel ()
		{
			skinsList = new Array( );
		}
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		// METHODE DE REFERENCEMENT DE L'OBSERVATEUR (OVERRIDE)
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		override public function registerView ( view : Object ) : void
		{
			super.addSubscriber ( view );
		}
		
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		// METHODES DE GESTION DU MODEL DE LA SKIN (génération de la skin -> affichage)
		/////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public function init( name : String, type : String ) : void
		{
			launch ( name, type );
		}
		
		public function launch ( name : String, type : String ) : void
		{			
			xmlLoader = new XmlLoader( name, type );
			if ( type == PlayerSpec.DISPATCH_SKIN_EVENT_TYPE )
				xmlLoader.addEventListener( XmlEvent.LOAD_SKIN_XML_COMPLETE, build, false );
			else if ( type == PlayerSpec.DISPATCH_SONGLIST_EVENT_TYPE )
				xmlLoader.addEventListener( XmlEvent.LOAD_SONGLIST_XML_COMPLETE, getReady, false );
			else
				throw new Error( "Le type de Xml à charger est erroné" );
		}		
		
		public function build ( pEvt : XmlEvent ) : void
		{
			// UTILE A LA PHASE DE TEST :: xmlParser.addEventListener( AvailableDataEvent.SKIN_DATA_READY, fin, false);
			xmlLoader.removeEventListener( XmlEvent.LOAD_SKIN_XML_COMPLETE, build, false ); 
			xmlParser.buildSkinModel ( pEvt, this );
		}
		
		public function getReady( ) : void
		{
			// cette méthode est désormais inutile puisque les sons ne sont pas encore intégrés au Model
		}
		
		public function addSkin ( pObj : Object ) : Boolean
		{
			for (var i:uint=0; i < this.skinsList.length; i++)
			{
				if (this.skinsList[i] == pObj.skinName)
				{
					return false;
				}
			}
			
			/*
			// PERMET DE VOIR CE QUI EST CHARGE DANS LE MODEL
			trace( "--\nadding new skin element :: " );
			var k : String;
			for ( var j : * in pObj )
			{
				k = j.toString();
				trace( j + " -> " + pObj[k] );
			}
			trace( "\n--" );
			*/
			
			this.skinsList.push ( pObj );
			super.notifyChanges ();
			return true;
		}
		
		// utile pour récupérer le nom d'un élément de skin via son index
		public function getNameAt( pNum : uint ) : String
		{
			if ( this.skinsList[pNum].sP != undefined )
			{
				var aName : String = this.skinsList[pNum].skinName;
				return aName;
			}
			else return null;
		}
		
		// utile pour récupérer l'index d'un élément de skin via son nom
		public function getPosAt( pStr : String ) : uint
		{
			for (var i:uint=0; i < this.skinsList.length; i++)
			{
				if ( this.skinsList[i].skinName == pStr )
				{
					var aPos : uint = this.skinsList[i].sP;
					return aPos;
				}				
			}
			return ECHEC_UINT; // un chiffre par convention, forcément plus grand que la taille de la liste
		}
		
		// utile pour vérifier s'il existe un élément de skin référencé à l'index spécifié
		public function existPosAt( pUint : uint ):Boolean
		{
			if ( getNameAt( pUint ) != null ) return true;
			return false;
		}
		
		// utile pour vérifier s'il existe un élément de skin référencé sous le nom indiqué
		public function existName( pStr : String ):Boolean
		{
			if ( getPosAt( pStr ) == ECHEC_UINT ) return false;
			return true;
		}
		
		// utile pour supprimer un élément de skin au nom ou à l'index spécifié
		public function removeSkin (name:*):Boolean
		{
				if (name is String)
				{
					var a : Boolean = existName(name);
					if ( a )
					{
						var i : uint = getPosAt( name );
						this.skinsList[i] = null;
						this.skinsList.splice (i,1);
						super.notifyChanges ();
						trace("removedSkin "+name);
						return true;
					}
					else
					{
						return false;
					}
				}
				else if ( name is uint )
				{
					var b : Boolean = existPosAt(name);
					if ( b )
					{
						this.skinsList[name] = null;
						this.skinsList.splice (name,1);
						super.notifyChanges ();
						trace("removedSkin "+name);
						throw new Error("l'index transmis à la fonction removeSkin n'existe pas");
						return true;
						
					}
					else
					{
						throw new Error("le nom transmis à la fonction removeSkin n'existe pas");
						return false;
					}
				}
				else throw new Error("la valeur passée à la fonction removeSkin doit être de type uint ou String");
				return false;
		}
		
		public function getSuscriber( pID : * ) : Object
		{
			if ( pID is uint )
			{				
				if ( existPosAt( pID ) )
					return this.skinsList[pID];
				else return null;
			}
			else if ( pID is String )
			{
				var pNum : uint = getPosAt( pID );
				if ( pNum != ECHEC_UINT )
					return this.skinsList[pNum];
				else return null;
			}
			else return null;
		}
	}
}